#include "kfifo_sp.h"
#include "c_mem.h"

#ifndef min
#define min(x,y) ((x)<(y)?(x):(y))
#endif

/*****************************************
*��������
*****************************************/
static void kfifo_copy_in(struct __kfifo *fifo, const void *src, unsigned int len, unsigned int off);
unsigned int __kfifo_out_peek(struct __kfifo *fifo, void *buf, unsigned int len);

#if 0
static inline unsigned int roundup_pow_of_two(unsigned int v);
static unsigned int rounddown_pow_of_two(unsigned int n);
#endif

/*******************************************************************
�������ƣ�kfifo_unused
����ԭ�ͣ�static inline unsigned int kfifo_unused(struct __kfifo *fifo)
��������������fifo��δʹ�õ�Ԫ������
����1   ���������ṹ��ָ��
����ֵ  ��fifo��δʹ�õ�Ԫ������
������Ϣ����  
*********************************************************************/

static inline unsigned int kfifo_unused(struct __kfifo *fifo)
{
	return (fifo->mask + 1) - (fifo->in - fifo->out);
}


/*******************************************************************
�������ƣ�kfifo_in
����ԭ�ͣ�unsinged int kfifo_in(struct __kfifo *fifo,const void *buf, unsigned int len)
���������������ݻ�����д��������
����1   ���������ṹ��ָ��
����2   ������ָ��
����3   ����ȡ���ݸ���
����ֵ  ����ȡ�ɹ�����
������Ϣ����  
*********************************************************************/
unsigned int __kfifo_in(struct __kfifo *fifo, const void *buf, unsigned int len)
{
	unsigned int l;

	l = kfifo_unused(fifo);
	if (len > l)
		len = l;

	kfifo_copy_in(fifo, buf, len, fifo->in);
	fifo->in += len;
	return len;
}

/*******************************************************************
�������ƣ�kfifo_out
����ԭ�ͣ�unsigned int kfifo_out(struct __kfifo *fifo, void *buf, unsigned int len)
���������������ݻ�����д��������
����1   ���������ṹ��ָ��
����2   ������ָ��
����3   ����ȡ���ݸ���
����ֵ  ����ȡ�ɹ�����
������Ϣ����  
*********************************************************************/
unsigned int __kfifo_out(struct __kfifo *fifo, void *buf, unsigned int len)
{
	len = __kfifo_out_peek(fifo, buf, len);
	fifo->out += len;
	return len;
}

/**********************************************
 * FIFO���� �ڲ�����
 **********************************************/
static void kfifo_copy_in(struct __kfifo *fifo, const void *src, unsigned int len, unsigned int off)
{
	unsigned int size = fifo->mask + 1;
	unsigned int esize = fifo->esize;
	unsigned int l;

	off &= fifo->mask;
	if (esize != 1) {
		off *= esize;
		size *= esize;
		len *= esize;
	}
	l = min(len, size - off);

	memcpy(fifo->data + off, src, l);
	memcpy(fifo->data, src + l, len - l);
	/*
	 * make sure that the data in the fifo is up to date before
	 * incrementing the fifo->in index counter
	 */
}


/**************************************************
 * FIFO���  �ڲ�����
 ****************************************************/
static void kfifo_copy_out(struct __kfifo *fifo, void *dst, unsigned int len, unsigned int off)
{
	unsigned int size = fifo->mask + 1;
	unsigned int esize = fifo->esize;
	unsigned int l;

	off &= fifo->mask;
	if (esize != 1) {
		off *= esize;
		size *= esize;
		len *= esize;
	}
	l = min(len, size - off);

	memcpy(dst, fifo->data + off, l);
	memcpy(dst + l, fifo->data, len - l);
	/*
	 * make sure that the data is copied before
	 * incrementing the fifo->out index counter
	 */
}

unsigned int __kfifo_out_peek(struct __kfifo *fifo, void *buf, unsigned int len)
{
	unsigned int l;

	l = fifo->in - fifo->out;
	if (len > l)
		len = l;

	kfifo_copy_out(fifo, buf, len, fifo->out);
	return len;
}

#if 0 
//��С��V������2����ָ�� 
//https://stackoverflow.com/questions/4398711/round-to-the-nearest-power-of-two
static inline unsigned int roundup_pow_of_two(unsigned int v) {
    v--;
    v |= v >> 1;
    v |= v >> 2;
    v |= v >> 4;
    v |= v >> 8;
    v |= v >> 16;
    v++;
    return v;
}
//�󲻴���n������2����ָ�� 
// https://blog.csdn.net/dreamispossible/article/details/91162847
static unsigned int rounddown_pow_of_two(unsigned int n) {
	n|=n>>1; 
    n|=n>>2; 
    n|=n>>4; 
    n|=n>>8; 
    n|=n>>16;
	return (n+1) >> 1;
}
#endif



